package algorithm.view.maze.generation;

import algorithm.view.common.AlgoHelpler;

import java.awt.*;
import java.util.LinkedList;
import java.util.Stack;

/**
 * @author bingo
 * @Description      动画控制层
 * @Date 2018/4/29
 */
public class AlgoVisualizer {

    private AlgoFrame algoFrame;

    private MazeData mazeData = null;

    private  int blockSize = 9;

    /**上下左右方向辅助数组*/
    private int[][]  d = {
            {-1,0},
            {0,1},
            {1,0},
            {0,-1}
    };


    public AlgoVisualizer(int l,int m) {
        mazeData = new MazeData(l,m);
        int senceWeight = mazeData.getM()*blockSize;
        int senceHeight = mazeData.getL()*blockSize;
        System.out.println("窗体高度："+senceHeight+"窗体宽度:"+senceWeight);
        EventQueue.invokeLater(()-> {
           algoFrame = new AlgoFrame("welcome", senceWeight, senceHeight);
           new Thread(()->{
                  run();
           }).start();

        });
    }

    public void run(){

      setData();

        //generation(mazeData.getEntranceX(),mazeData.getEntranceY()+1);
       //generation2();
       // generation3();
        generation4();
      setData();

    }

    /**递归方式走迷宫*/
    private void generation(int x, int y) {
        mazeData.visited[x][y] = true;
        for(int i = 0;i < 4;i++){
            int newX =  x  + d[i][0]*2;
            int newY =  y  + d[i][1]*2;
            if(mazeData.inArea(newX,newY)&& !mazeData.visited[newX][newY]){
                int  x1 = x+d[i][0];
                int  y1 = y+d[i][1];
                if(mazeData.inArea(x1,y1)){
                    mazeData.data[x1][y1] = MazeData.RODE;
                }
                setData();
                generation(newX,newY);
            }
        }
    }


    /**非递归方式走迷宫*/
    private void generation2(){
        Stack<Position> stack =  new Stack();
        stack.push(new Position(mazeData.getEntranceX(),mazeData.getEntranceY()+1));
        mazeData.visited[mazeData.getEntranceY()][mazeData.getEntranceY()+1] = true;
        while (!stack.isEmpty()){
         Position position = stack.pop();
          for(int i=0;i<4;i++){
              int newX = position.getX() + d[i][0]*2;
              int newY = position.getY() + d[i][1]*2;
              if(mazeData.inArea(newX,newY)&& !mazeData.visited[newX][newY]) {
                  mazeData.visited[newX][newY] = true;
                  int x1 = position.getX() + d[i][0];
                  int y1 = position.getY() + d[i][1];
                  if (mazeData.inArea(x1, y1)) {
                      mazeData.data[x1][y1] = MazeData.RODE;
                  }
                  setData();
                  stack.push(new Position(newX,newY));
              }

          }

        }

    }

    /**广度优先遍历走迷宫*/
    private void generation3(){
        LinkedList<Position> queue = new LinkedList();
        queue.add(new Position(mazeData.getEntranceX(),mazeData.getEntranceY()+1));
        mazeData.visited[mazeData.getEntranceX()][mazeData.getEntranceY()+1] = true;
        while (queue.size()!=0){
            Position position = queue.pop();
            for(int i=0;i<4;i++){
                int newX = position.getX()+d[i][0]*2;
                int newY = position.getY()+d[i][1]*2;
                if(mazeData.inArea(newX,newY)&& !mazeData.visited[newX][newY]){
                    int x1 = position.getX() + d[i][0];
                    int y1 = position.getY() + d[i][1];
                    mazeData.visited[newX][newY] = true;
                    if (mazeData.inArea(x1, y1)) {
                        mazeData.data[x1][y1] = MazeData.RODE;
                    }
                    setData();
                    queue.addLast(new Position(newX,newY));
                }
            }

        }
    }

    /**广度优先遍历随机走走迷宫*/
    private void generation4(){
        RandomQueue<Position> queue = new RandomQueue();
        queue.add(new Position(mazeData.getEntranceX(),mazeData.getEntranceY()+1));
        mazeData.visited[mazeData.getEntranceX()][mazeData.getEntranceY()+1] = true;
        mazeData.opMist(mazeData.getEntranceX(),mazeData.getEntranceY());
        while (queue.size()!=0){
            Position position = queue.removeElement();
            for(int i=0;i<4;i++){
                int newX = position.getX()+d[i][0]*2;
                int newY = position.getY()+d[i][1]*2;
                if(mazeData.inArea(newX,newY)&& !mazeData.visited[newX][newY]){
                    int x1 = position.getX() + d[i][0];
                    int y1 = position.getY() + d[i][1];
                    mazeData.opMist(newX,newY);
                    mazeData.visited[newX][newY] = true;
                    if (mazeData.inArea(x1, y1)) {
                        mazeData.data[x1][y1] = MazeData.RODE;
                    }
                    setData();
                    queue.add(new Position(newX,newY));
                }
            }

        }
    }

    public void setData(){
        algoFrame.render(mazeData);
        AlgoHelpler.pause(5);

    }

}
